package com.tlvip.design.chain;

/**
 * <p>description：责任链模式</p>
 * 应用场景：一个请求的处理需要多个对象中的一个或几个协作处理
 * <p>
 * 优点：
 * 1 请求的发送者和接收者解耦
 * 2 可以控制执行顺序
 * 3 符合开闭原则和单一职责原则
 * <p>
 * 经典案例
 * javax.servlet.Filter
 *
 *
 * <p>copyright： copyright(C)2016-2099</p>
 * <p>Life is short,we need passion</p>
 * <p>Summary： </p>
 * <p>instructions： </p>
 * Date 2021/8/14</p>
 * Author mac
 *
 * @version 1.0
 */
public class ChainOfResponsibility {

    public static void main(String[] args) {
        Request request = new Request(true, true);
        RequestFrequentHandler requestFrequentHandler = new RequestFrequentHandler(new LoggingHandler(null));
        if (requestFrequentHandler.process(request)) {
            System.out.println("正常业务处理");
        } else {
            System.out.println("访问异常");
        }
    }
}

// 本质上是通过定义一组对象，相互间通过链式存储，处理相同对象的不同部分，并返回一致的结果
// filter 特别适合
abstract class Handler {
    Handler next;

    public Handler(Handler next) {
        this.next = next;
    }

    public Handler getNext() {
        return next;
    }

    abstract boolean process(Request request);
}

class RequestFrequentHandler extends Handler {
    public RequestFrequentHandler(Handler next) {
        super(next);
    }

    @Override
    boolean process(Request request) {
        System.out.println("访问频率控制");
        if (request.isFrequentOk()) {
            Handler handler = getNext();
            if (null == handler) {
                return true;
            }
            return next.process(request);
        }
        return false;
    }
}

class LoggingHandler extends Handler {
    public LoggingHandler(Handler next) {
        super(next);
    }

    @Override
    boolean process(Request request) {
        System.out.println("登录验证");
        if (request.isLoggedOn()) {
            Handler handler = getNext();
            if (null == handler) {
                return true;
            }
            return next.process(request);
        }
        return false;
    }
}

class Request {
    private final boolean loggedOn;
    private final boolean frequentOk;

    public Request(boolean loggedOn, boolean frequentOk) {
        this.loggedOn = loggedOn;
        this.frequentOk = frequentOk;
    }

    public boolean isFrequentOk() {
        return frequentOk;
    }

    public boolean isLoggedOn() {
        return loggedOn;
    }
}
